package com.myk.game.gobangchess.rooms;

import com.myk.game.gobangchess.Room;
import com.myk.game.gobangchess.Sign;
import com.myk.game.gobangchess.constants.ColorCost;
import com.myk.game.gobangchess.constants.WinMode;
import com.myk.game.gobangchess.signs.*;
import com.myk.game.gobangchess.utils.GridsUtils;
import com.myk.game.gobangchess.utils.Pair;

import java.util.*;

/**
 * 七搏Seven Beats
 */
public class SevenBeatsRoom extends Room {

    private CacheSign cacheSign; //缓存标记
    private static int BLACK_SLOT_ROW; //黑方棋槽所在行
    private static int WHITE_SLOT_ROW; //白方棋槽所在行
    private List<Chess> chessList; //场上棋子集合
    private Komadai blackKomadai; //黑方驹台
    private Komadai whiteKomadai; //白方驹台
    private Chess choose; //当前选中的棋子
    private Chess select; //当前选中的俘虏
    private GroundSign dropTip;//打入坐标提示
    private LineSign moveTip;//移动箭头提示
    private int captureCnt1,captureCnt2; //吃子数计数器，用于判断胜负

    public SevenBeatsRoom(String roomName) {
        super(roomName, "第三届设计比赛参赛作品，快节奏的对攻棋，由佑航设计。", "七搏", GridsUtils.createEmptyGrids(9, 9), true, false);
        initChessBoardStyle();
    }

    //初始化背景样式
    private void initChessBoardStyle() {
        BLACK_SLOT_ROW = 0;
        WHITE_SLOT_ROW = 8;

        List<Sign> chessboardStyle = new ArrayList<>();
        int row = curGrids.length;
        int col = curGrids[0].length;

        //将画布默认格子隐藏了
        chessboardStyle.add(new GroundSign(getIndex(0, 0), getIndex(row - 1, col - 1), ColorCost.TABLECLOTH_COLOR, ColorCost.TABLECLOTH_COLOR, 2.0f, 0, 0));

        //画棕棋盘颜色
        chessboardStyle.add(new GroundSign(getIndex(0, 0), getIndex(row - 1, col - 1), "#FFDD976D", "#FFC57555", 1f, 0, 0));

        //绘制底纹模拟木纹
        List<Integer> allIds = new ArrayList<>();
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                allIds.add(getIndex(i, j));
            }
        }
        FigureSign figure = FigureSign.makeBatchSingleFigure(allIds, "#99C57555");
        int version = 33;
        figure.setMidSideLine(1, 1, 1, 1, 1, 1, 1, 1); //还OK
        chessboardStyle.add(figure);

        //画半透明黑白相间的格子
        List<Integer> whiteGrids = new ArrayList<>();
        List<Integer> blackGrids = new ArrayList<>();
        for (int i = 1; i < row-1; i++) {
            for (int j = 1; j < col-1; j++) {
                int index = getIndex(i, j);
                if ((i + j) % 2 == 0) {
                    whiteGrids.add(index);
                }
                else {
                    blackGrids.add(index);
                }
            }
        }
        chessboardStyle.add(new ColorSign(blackGrids, "#BB333333"));
        chessboardStyle.add(new ColorSign(whiteGrids, "#BBDDDDDD"));

        //画棋盘格子线
        for (int i = 1; i < row; i++) {
            List<Pair<Integer, Integer>> nodes1 = new ArrayList<>();
            nodes1.add(new Pair<>(getIndex(i, 1), 0)); //起点
            nodes1.add(new Pair<>(getIndex(i, col - 2), 2)); //终点
            chessboardStyle.add(new PathSign(nodes1, "#FF000000", "#00000000", 1f, 0));
        }
        for (int j = 1; j < col; j++) {
            List<Pair<Integer, Integer>> nodes1 = new ArrayList<>();
            nodes1.add(new Pair<>(getIndex(1, j), 0)); //起点
            nodes1.add(new Pair<>(getIndex(row - 2, j), 6)); //终点
            chessboardStyle.add(new PathSign(nodes1, "#FF000000", "#00000000", 1f, 0));
        }

        //画棋盘外边框
        List<Pair<Integer, Integer>> nodes1 = new ArrayList<>();
        nodes1.add(new Pair<>(getIndex(1, 1), 0));
        nodes1.add(new Pair<>(getIndex(1, col - 2), 2));
        nodes1.add(new Pair<>(getIndex(row - 2, col - 2), 8));
        nodes1.add(new Pair<>(getIndex(row - 2, 1), 6));
        nodes1.add(new Pair<>(getIndex(1, 1), 0));
        nodes1.add(new Pair<>(getIndex(1, col - 2), 2));
        chessboardStyle.add(new PathSign(nodes1, "#FF000000", "#00000000", 1f, 0));

        //添加到缓存标记中
        cacheSign = new CacheSign(this, "background", version, true, chessboardStyle); //*** 修改背景样式记得改这里的版本号！！！
    }

    @Override
    public String getRuleText() {
        return "《七搏》\n\n" +
                "基本规则：\n黑线，双方轮流行动，移动或打入一枚棋驹。\n吃子成为持驹，打入无限制。\n无升变。\n\n" +
                "胜负判断：\n若一方吃子后，对方没有立即\"反吃\"，则判负。\n注：完成\"兑子\"后不必立即再吃子。\n\n" +
                "棋驹走法：\n" +
                "角行—斜不限\n飛車—直不限\n風鱉—竖不限+斜前1\n猛豹—竖1+斜1\n" +
                "嗔豬—横1+斜1 (猪猪可爱！)\n金将—直1+斜前1\n天馬—竖向马步+横前马步";
    }

    @Override
    public String getCoordMode() {
        return "41411111";
    }

    @Override
    public CacheSign getCacheSignByName(String cacheName) {
        return cacheSign;
    }

    @Override
    public String getGameInfo() {
        //先全部初始化
        curGrids = GridsUtils.copyGrids(originGrids);
        signList.clear();
        signList.add(cacheSign);

        //根据chessList集合和choose对象来生成要显示到客户端的布局和标记
        if (chessList != null && !chessList.isEmpty()) {
            //绘制棋子
            for (Chess chess : chessList) {
                //棋子自身形象在内部绘制
                chess.drawSelf(this);
                //表示方向的小箭头则在外部绘制
                if (chess.side == 1) {
                    signList.add(new TitleSign((chess.col + 0.5f) / curGrids[0].length, (chess.row + 0.785f) / curGrids.length, 0, "▼", "#FF111111", 0.1f));
                }
                else {
                    signList.add(new TitleSign((chess.col + 0.5f) / curGrids[0].length, (chess.row + 0.215f) / curGrids.length, 0, "▲", "#FFEEEEEE", 0.1f));
                }
            }
            //绘制驹台
            if (blackKomadai != null && whiteKomadai != null) {
                blackKomadai.drawSelf(this);
                whiteKomadai.drawSelf(this);
            }
            //绘制打入坐标框框
            if (dropTip != null) {
                signList.add(dropTip);
            }
            //绘制主动移动箭头
            if (moveTip != null) {
                signList.add(moveTip);
            }
            //绘制对弈时的选中棋子移动状态
            if (choose != null) {
                choose.drawCanMovedPath(this); //绘制棋子可移动路径
            }
            //绘制对弈时选中的俘虏可打入路径
            if (select != null) {
                select.drawCanDropPos(this); //绘制俘虏可打入的位置
            }
        }
        return super.getGameInfo();
    }

    @Override
    protected void onStartPrepare() {
        captureCnt1=0; captureCnt2=0;
        initChessList(); //重新创建初始布局的棋子
    }

    private void initChessList() {
        chessList = new ArrayList<>();
        blackKomadai = new Komadai(1, this);
        whiteKomadai = new Komadai(2, this);
        final int setupCnt=16;
        final int[] RowB ={2,1,1,1,2,1,1,2,2,2,2,1,2,1,2,2},ColB ={5,3,5,4,6,4,4,5,4,2,4,5,5,2,3,4};
        final int[] RowR ={1,1,2,2,1,1,1,2,2,1,2,1,2,2,1,1},ColR ={5,6,4,4,3,5,6,3,3,5,5,4,4,4,5,5};
        final int[] RowWT={1,1,1,1,1,1,1,1,1,1,2,2,2,1,1,1},ColWT={3,2,4,5,5,3,2,5,5,3,3,4,3,4,3,3};
        final int[] RowFL={2,2,3,3,3,2,2,3,3,3,3,1,3,2,3,2},ColFL={6,2,3,3,5,5,2,3,3,3,3,2,5,3,3,5};
        final int[] RowAB={2,2,3,3,3,2,2,3,3,3,3,1,3,2,3,2},ColAB={2,6,5,5,3,3,6,5,5,5,5,6,3,5,5,3};
        final int[] RowG ={2,2,3,3,3,3,1,3,2,2,3,3,3,3,2,3},ColG ={3,4,4,4,4,4,5,4,5,6,4,4,4,4,5,4};
        final int[] RowPe={1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1},ColPe={4,5,3,3,2,4,3,3,3,4,4,3,4,6,4,4};

        final String[] setupName={"34","43","313-1","313-2","223-1","331-1","52","223-2",
            "232","322-1","133-1","511","133-2","331-2","322-2","331-3"};

       // 在规则书给出的布置中随机选择一种
        int setupId=(int)(Math.random()*setupCnt);
        gameTip = "当前开局编号："+setupName[setupId];
        chessList.add(new Bishop(1, RowB[setupId], ColB[setupId]));
        chessList.add(new Rook(1, RowR[setupId], ColR[setupId]));
        chessList.add(new WindTortoise(1, RowWT[setupId], ColWT[setupId]));
        chessList.add(new FeoriousLeopard(1, RowFL[setupId], ColFL[setupId]));
        chessList.add(new AngryBoar(1, RowAB[setupId], ColAB[setupId]));
        chessList.add(new Gold(1, RowG[setupId], ColG[setupId]));
        chessList.add(new Pegasus(1, RowPe[setupId], ColPe[setupId]));
        chessList.add(new Bishop(2, 8-RowB[setupId], 8-ColB[setupId]));
        chessList.add(new Rook(2, 8-RowR[setupId], 8-ColR[setupId]));
        chessList.add(new WindTortoise(2, 8-RowWT[setupId], 8-ColWT[setupId]));
        chessList.add(new FeoriousLeopard(2, 8-RowFL[setupId], 8-ColFL[setupId]));
        chessList.add(new AngryBoar(2, 8-RowAB[setupId], 8-ColAB[setupId]));
        chessList.add(new Gold(2, 8-RowG[setupId], 8-ColG[setupId]));
        chessList.add(new Pegasus(2, 8-RowPe[setupId], 8-ColPe[setupId]));

        noticeBlackMove();
    }

    @Override
    public void resetGrids() {
        super.resetGrids();
        chessList = null;
        blackKomadai = null;
        whiteKomadai = null;
        choose = null;
        select = null;
        dropTip = null;
        moveTip = null;
        captureCnt1=0; captureCnt2=0;
    }

    @Override
    public void doRule(int row, int col, int value) {
        boolean isFightArea = isFightArea(row, col); //判断点击的是棋盘还是驹台
        boolean isChooseOrSelect = choose != null || select != null; //判断是否选定了要移动或打入的棋子
        //无选中等待选棋时
        if (!isChooseOrSelect) {
            if (isFightArea) {
                //选择场上棋子
                Chess chess = getChessByPos(row, col);
                if (chess != null && chess.side == value) {
                    chooseChess(chess);
                    noticeAllRefreshGameInfo();
                }
            }
            else {
                //选择己方驹台俘虏
                Chess captive = getCaptiveByPos(row, col);
                if (captive != null) {
                    selectCaptive(captive);
                    noticeAllRefreshGameInfo();
                }
            }
        }
        //有选中等待落子时
        else {
            if (isFightArea) {
                //选中场上棋子等待移动时
                if (choose != null) {
                    if (choose.isPosCanMove(row, col, this)) {
                        moveChess(row, col, choose); //移动棋子
                        checkOver(value); //检查胜负
                    }
                    else {
                        clearChooseSelect();
                        noticeAllRefreshGameInfo();
                    }
                }
                //选中驹台俘虏准备打入时
                else {
                    if (select.isPosCanDrop(row, col, this)) {
                        dropChess(row, col, select); //打入棋子
                        checkOver(value); //检查胜负
                    }
                    else {
                        clearChooseSelect();
                        noticeAllRefreshGameInfo();
                    }
                }
            }
            else {
                clearChooseSelect();
                noticeAllRefreshGameInfo();
            }
        }
    }

    /**
     * 移动棋子
     */
    private void moveChess(int row, int col, Chess chess) {
        dropTip = null;
        moveTip = new LineSign(getIndex(chess.row, chess.col), getIndex(row, col), ColorCost.MOVE_ARROW_LIGHT, 1); //添加移动箭头提示
        Chess enemyChess = getChessByPos(row, col);
        if (enemyChess != null) {
            captureChess(enemyChess); //俘虏敌方棋子
        }
        chess.row = row;
        chess.col = col;
        chess.selected = false;
        choose = null;
    }

    /**
     * 捕获棋子
     */
    private void captureChess(Chess enemyChess) {
        if (enemyChess.side == 1) { //黑棋被俘虏
            captureCnt2++; //修改吃子计数器
            chessList.remove(enemyChess);
            whiteKomadai.addChess(enemyChess);
            enemyChess.side = 2;
        }
        else { //白棋被俘虏
            captureCnt1++;
            chessList.remove(enemyChess);
            blackKomadai.addChess(enemyChess);
            enemyChess.side = 1;
        }
    }

    /**
     * 选中俘虏
     */
    private void selectCaptive(Chess captive) {
        if (select != null) select.selected = false;
        select = captive;
        select.selected = true;
    }

    /**
     * 打入棋子
     */
    private void dropChess(int row, int col, Chess captureChess) {
        moveTip = null;
        dropTip = new GroundSign(getIndex(row, col), ColorCost.TRANSPARENT, ColorCost.NEW_PUT_POINT_LIGHT, 1.0f, 1, 0); //添加打入点提示
        if (cur == 1) {
            blackKomadai.removeChess(captureChess);
        }
        else {
            whiteKomadai.removeChess(captureChess);
        }
        captureChess.side = cur;
        captureChess.row = row;
        captureChess.col = col;
        captureChess.selected = false;
        chessList.add(captureChess);
        select = null;
    }

    /**
     * 选中棋子
     */
    private void chooseChess(Chess chess) {
        if (choose != null) choose.selected = false;
        choose = chess;
        choose.selected = true;
    }

    /**
     * 取消各种选中状态
     */
    private void clearChooseSelect() {
        if (choose != null) {
            choose.selected = false;
            choose = null;
        }
        if (select != null) {
            select.selected = false;
            select = null;
        }
    }

    /**
     * 判断游戏是否结束
     */
    private void checkOver(int curIsBlack) {
        stepAdd(); //增加回合计数
        if(curIsBlack==1){
            //黑方回合结束时，黑方吃子数必须大于等于白方，否则输；白方同理
            if(captureCnt1<captureCnt2){
                gameTip = "白方获胜！";
                doOver(WinMode.WHITE_WIN, "白方获胜！");
            }else if(captureCnt1>captureCnt2 && !checkCanCapture(2)){
                //若大于白方且白方不能吃子，就赢了
                gameTip = "白方无法吃子，黑方获胜！";
                doOver(WinMode.BLACK_WIN, "白方无法吃子，黑方获胜！");
            }else{
                if(captureCnt1>captureCnt2){
                    gameTip = "白方若不吃子，将会输棋！";
                }else gameTip = "-1";
                noticeWhiteMove();
            }
        }else{
            if(captureCnt1>captureCnt2){
                gameTip = "黑方获胜！";
                doOver(WinMode.BLACK_WIN, "黑方获胜！");
            }else if(captureCnt1<captureCnt2 && !checkCanCapture(1)){
                gameTip = "黑方无法吃子，白方获胜！";
                doOver(WinMode.WHITE_WIN, "黑方无法吃子，白方获胜！");
            } else {
                if(captureCnt1<captureCnt2){
                    gameTip = "黑方若不吃子，将会输棋！";
                }else gameTip = "-1";
                noticeBlackMove();
            }
        }
    }


    /**
     * 判断某一方下一手能不能吃子
     */
    private boolean checkCanCapture(int side){
        boolean flag=false;
        for(Chess curPiece : chessList){
            if(curPiece.side!=side) continue;
            for(Chess tarPiece : chessList){
                if(tarPiece.side==side) continue;
                if(tarPiece.row==0 || tarPiece.row==8 || tarPiece.col==0 || tarPiece.col==8)
                    continue;
                if(curPiece.isPosCanMove(tarPiece.row, tarPiece.col, this)){
                    flag=true; break;
                }
            }
            if(flag) break;
        }
        return flag;
    }

    /**
     * 判断坐标是否在对战区域
     * 棋盘对战区域是在整个9x9的二维数组中间7x7之中。
     */
    private boolean isFightArea(int row, int col) {
        return row >= 1 && row <= curGrids.length - 2 && col >= 1 && col <= curGrids[0].length - 2;
    }

    /**
     * 根据坐标搜索棋子
     */
    private Chess getChessByPos(int row, int col) {
        for (Chess chess : chessList) {
            if (chess.row == row && chess.col == col) {
                return chess;
            }
        }
        return null;
    }

    /**
     * 根据坐标搜索俘虏棋子
     */
    private Chess getCaptiveByPos(int row, int col) {
        if (this.cur == 1) {
            return blackKomadai.getChessByPos(getIndex(row, col));
        }
        else {
            return whiteKomadai.getChessByPos(getIndex(row, col));
        }
    }

    /**
     * 驹台
     * （黑方驹台所包含的棋子都是白方棋子，白方驹台所有包含的棋子都是黑方棋子）
     */
    private static class Komadai {

        private final int[] SLOT_INDEXES; //棋槽对应游戏网格界面的坐标
        private final String[] slotHeads; //每个棋槽的棋头排序，存放棋子的originType,可知最多7种  燕(雁)，鹤，雉，左鹑，右鹑，鹰(雕)，鹏
        private final int side; //驹台阵营，1：黑方，2：白方
        private final Map<String, List<Chess>> captiveMap; //被俘虏棋子容器

        public Komadai(int side, SevenBeatsRoom room) {
            if (side == 1) {
                //黑方驹台棋槽坐标 （顶部从左往右）
                SLOT_INDEXES = new int[]{
                        room.getIndex(0, 0),
                        room.getIndex(0, 1),
                        room.getIndex(0, 2),
                        room.getIndex(0, 3),
                        room.getIndex(0, 4),
                        room.getIndex(0, 5),
                        room.getIndex(0, 6)
                };
            }
            else {
                //白方驹台棋槽坐标 （底部从右往左）
                SLOT_INDEXES = new int[]{
                        room.getIndex(8, 8),
                        room.getIndex(8, 7),
                        room.getIndex(8, 6),
                        room.getIndex(8, 5),
                        room.getIndex(8, 4),
                        room.getIndex(8, 3),
                        room.getIndex(8, 2)
                };
            }
            slotHeads = new String[7];
            this.side = side;
            this.captiveMap = new HashMap<>();
        }

        /**
         * 添加被俘虏的棋子
         */
        public void addChess(Chess chess) {
            chess.upgrade = false; //棋子被俘虏蜕回前身棋
            String type = chess.getOriginType();
            for (int i = 0; i < slotHeads.length; i++) {
                if (slotHeads[i] == null) { //按照顺序添加，遇到空位就初始添加整个头部索引和集合容器
                    slotHeads[i] = type;
                    List<Chess> chessArray = new ArrayList<>();
                    chessArray.add(chess);
                    captiveMap.put(type, chessArray);
                    break;
                }
                else if (slotHeads[i].equals(type)) { //找到自己所在的集合
                    captiveMap.get(type).add(chess);
                    break;
                }
            }
        }

        /**
         * 从驹台中拿走棋子
         */
        public void removeChess(Chess chess) {
            //移除被俘虏棋子，外部保证改棋子肯定在驹台的集合中
            List<Chess> list = captiveMap.get(chess.getOriginType());
            list.remove(chess);
            //如果某种棋子数量为0了，移除集合容器，还要移除棋头，然后棋头数组还要往前挪动
            if (list.isEmpty()) {
                captiveMap.remove(chess.getOriginType());
                boolean flag = false;
                for (int i = 0; i < slotHeads.length; i++) {
                    if (flag) {
                        slotHeads[i - 1] = slotHeads[i];
                    }
                    else if (slotHeads[i].equals(chess.getOriginType())) {
                        slotHeads[i] = null;
                        flag = true;
                    }
                }
            }
        }

        /**
         * 根据坐标查询俘虏棋子
         */
        public Chess getChessByPos(int index) {
            for (int i = 0; i < SLOT_INDEXES.length; i++) {
                if (SLOT_INDEXES[i] == index) { //找到格子索引对应棋槽的序号
                    if (slotHeads[i] != null)
                        return captiveMap.get(slotHeads[i]).get(0); //通过序号对应棋头找到俘虏棋子的集合容器，返回其中任意一个棋子
                    else return null;
                }
            }
            return null;
        }

        /**
         * 绘制驹台和驹台上的棋子
         */
        public void drawSelf(SevenBeatsRoom room) {
            for (int i = 0; i < slotHeads.length; i++) { //按照棋头排序顺序进行绘制
                if (slotHeads[i] != null) {
                    List<Chess> chessList = captiveMap.get(slotHeads[i]);
                    Chess indexChess = chessList.get(0); //取一个棋子作为绘制模板，添加的时候肯定会添加第一个，移除的时候棋头和chess列表都会移除
                    //给绘制模板设置属性用于绘制
                    indexChess.side = side;
                    indexChess.row = room.getRowByIndex(SLOT_INDEXES[i]);
                    indexChess.col = room.getColByIndex(SLOT_INDEXES[i]);
                    //棋子自身形象内部绘制
                    indexChess.drawSelf(room);
                    //相同类型棋子数量在外部绘制
                    if (side == 1) {
                        room.signList.add(new BadgeSign(SLOT_INDEXES[i], "x" + chessList.size(), 1, "#FFCC0000", "#00000000"));
                    }
                    else {
                        room.signList.add(new BadgeSign(SLOT_INDEXES[i], "x" + chessList.size(), 7, "#FFCC0000", "#00000000"));
                    }
                }
            }
        }

    }

    /**
     * 棋子基类
     */
    private abstract static class Chess {

        public int side; //棋子阵营，1：黑方，2：白方
        public int row; //棋子所在行数
        public int col;//棋子所在列数
        public boolean upgrade; //是否升变
        public boolean selected; //是否被选中

        public Chess(int side, int row, int col) {
            this.side = side;
            this.row = row;
            this.col = col;
            this.upgrade = false;
            this.selected = false;
        }

        /**
         * 获取棋子的纹饰名称
         */
        public abstract String getName();

        /**
         * 个性化移动限制算法
         */
        public abstract boolean isPosCanMove(int row, int col, SevenBeatsRoom room);

        /**
         * 判断该位置是否可以打入
         */
        protected boolean isPosCanDrop(int row, int col, SevenBeatsRoom room) {
            return generalDropLimit(row, col, room);
        }

        /**
         * 获取棋类标签
         */
        public String getOriginType() {
            return getClass().getSimpleName();
        }

        /**
         * 坐标与棋子之间有其它棋子阻碍
         */
        protected boolean hasPieceInBetween(int startX, int startY, int endX, int endY, int[][] board) {
            // 检查是否在同一行
            if (startX == endX) {
                for (int i = Math.min(startY, endY) + 1; i < Math.max(startY, endY); i++) {
                    if (board[startX][i] != 0) return true;
                }
            }
            // 检查是否在同一列
            else if (startY == endY) {
                for (int i = Math.min(startX, endX) + 1; i < Math.max(startX, endX); i++) {
                    if (board[i][startY] != 0) return true;
                }
            }
            // 检查是否在同一条对角线上
            else if (Math.abs(startX - endX) == Math.abs(startY - endY)) {
                int deltaX = startX < endX ? 1 : -1;
                int deltaY = startY < endY ? 1 : -1;

                for (int x = startX + deltaX, y = startY + deltaY; x != endX && y != endY; x += deltaX, y += deltaY) {
                    if (board[x][y] != 0) return true;
                }
            }
            // 如果不在同一行、同一列或同一条对角线上，直接返回 false
            return false;
        }

        //公共移动限制
        protected boolean generalMoveLimit(int side,int row, int col, SevenBeatsRoom room) {
            if (room.getChessByPos(row, col) != null) {
                return side != (room.getChessByPos(row,col)).side; //不能移动到已有自己棋子的地方
            }else return true;
        }

        //公共的打入限制
        protected boolean generalDropLimit(int row, int col, SevenBeatsRoom room) {
            return room.curGrids[row][col] == 0; //不能移动到已有棋子的地方
        }

        /**
         * 获取可移动范围列表
         */
        public List<int[]> getCanMovedPos(SevenBeatsRoom room) {
            List<int[]> canMovedPosList = new ArrayList<>();
            int startRow = 1;
            int startCol = 1;
            int endRow = room.curGrids.length - 1;
            int endCol = room.curGrids[0].length - 1;
            for (int i = startRow; i < endRow; i++) {
                for (int j = startCol; j < endCol; j++) {
                    if (isPosCanMove(i, j, room)) {
                        canMovedPosList.add(new int[]{i, j});
                    }
                }
            }
            return canMovedPosList;
        }

        /**
         * @param room
         * @return
         */
        private List<int[]> getCanDropPos(SevenBeatsRoom room) {
            List<int[]> canDropPosList = new ArrayList<>();
            int startRow = 1;
            int startCol = 1;
            int endRow = room.curGrids.length - 1;
            int endCol = room.curGrids[0].length - 1;
            for (int i = startRow; i < endRow; i++) {
                for (int j = startCol; j < endCol; j++) {
                    if (isPosCanDrop(i, j, room)) {
                        canDropPosList.add(new int[]{i, j});
                    }
                }
            }
            return canDropPosList;
        }

        /**
         * 个性化绘制
         */
        public void drawSelf(SevenBeatsRoom room) {
            String[] nameStrs = this.getName().split("");
            if (side == 1) {
                room.curGrids[row][col] = selected ? 32 : 22;
                room.signList.add(new TitleSign((this.col + 0.5f) / room.curGrids[0].length, (this.row + 0.255f) / room.curGrids.length, 0, nameStrs[0], "#FF333333", 0.28f));
                room.signList.add(new TitleSign((this.col + 0.5f) / room.curGrids[0].length, (this.row + 0.535f) / room.curGrids.length, 0, nameStrs[1], "#FF333333", 0.28f));
            }
            else {
                room.curGrids[row][col] = selected ? 31 : 21;
                room.signList.add(new TitleSign((this.col + 0.5f) / room.curGrids[0].length, (this.row + 0.365f) / room.curGrids.length, 0, nameStrs[0], "#FF333333", 0.28f));
                room.signList.add(new TitleSign((this.col + 0.5f) / room.curGrids[0].length, (this.row + 0.645f) / room.curGrids.length, 0, nameStrs[1], "#FF333333", 0.28f));
            }
        }

        /**
         * 绘制可移动路径
         */
        public void drawCanMovedPath(SevenBeatsRoom room) {
            List<int[]> canMovedPosList = getCanMovedPos(room); //获取该棋子可移动到的格子的坐标集合
            if (!canMovedPosList.isEmpty()) {
                for (int[] canMovedPos : canMovedPosList) {
                    room.signList.add(new TitleSign((canMovedPos[1] + 0.5f) / room.curGrids[0].length, (canMovedPos[0] + 0.5f) / room.curGrids.length, 0, "●", "#9988EE88", 0.333f));
                }
            }
        }

        /**
         * 绘制可打入位置
         */
        public void drawCanDropPos(SevenBeatsRoom room) {
            List<int[]> canDropPosList = getCanDropPos(room); //获取该棋子可移动到的格子的坐标集合
            if (!canDropPosList.isEmpty()) {
                for (int[] canMovedPos : canDropPosList) {
                    room.signList.add(new TitleSign((canMovedPos[1] + 0.5f) / room.curGrids[0].length, (canMovedPos[0] + 0.5f) / room.curGrids.length, 0, "●", "#9988EE88", 0.333f));
                }
            }
        }

    }

    //角行
    private static class Bishop extends Chess {
        public Bishop(int side, int row, int col) {
            super(side, row, col);
        }

        @Override
        public String getName() { return "角行";}

        @Override
        public boolean isPosCanMove(int row, int col, SevenBeatsRoom room) {
            if(col==this.col && row==this.row) return false;
            if(Math.abs(row-this.row)!=Math.abs(col-this.col)) return false;
            if (hasPieceInBetween(row, col, this.row, this.col, room.curGrids)) return false;
            return generalMoveLimit(side, row, col, room);
        }
    }
    //飞车
    private static class Rook extends Chess {
        public Rook(int side, int row, int col) {
            super(side, row, col);
        }

        @Override
        public String getName() { return "飛車";}

        @Override
        public boolean isPosCanMove(int row, int col, SevenBeatsRoom room) {
            if(col==this.col && row==this.row) return false;
            if(!(col==this.col || row==this.row)) return false;
            if (hasPieceInBetween(row, col, this.row, this.col, room.curGrids)) return false;
            return generalMoveLimit(side, row, col, room);
        }
    }
    //风鳖
    private static class WindTortoise extends Chess {
        public WindTortoise(int side, int row, int col) {
            super(side, row, col);
        }

        @Override
        public String getName() { return "風鱉";}

        @Override
        public boolean isPosCanMove(int row, int col, SevenBeatsRoom room) {
            if(col==this.col && row==this.row) return false;
            if(side==1){
                if (col!=this.col){ //可以走竖
                    if(row<this.row) return false; //只能走斜前1格
                    if(Math.abs(col-this.col)!=1 || Math.abs(row-this.row)!=1) return false;
                }
            }else if(side==2){
                if (col!=this.col){
                    if(row>this.row) return false;
                    if(Math.abs(col-this.col)!=1 || Math.abs(row-this.row)!=1) return false;
                }
            }
            if (hasPieceInBetween(row, col, this.row, this.col, room.curGrids)) return false;
            return generalMoveLimit(side, row, col, room);
        }
    }
    //猛豹
    private static class FeoriousLeopard extends Chess {
        public FeoriousLeopard(int side, int row, int col) {
            super(side, row, col);
        }

        @Override
        public String getName() { return "猛豹";}

        private final int disCnt=6;
        private final int[] disIndexRow={-1,-1,-1,1,1,1};
        private final int[] disIndexCol={-1,0,1,-1,0,1};

        @Override
        public boolean isPosCanMove(int row, int col, SevenBeatsRoom room) {
            boolean flag=false;
            int disRow=row-this.row,disCol=col-this.col;
            for(int i=0;i<this.disCnt;i++){
                if(disRow==this.disIndexRow[i] && disCol==this.disIndexCol[i]){
                    flag=true;
                    break;
                }
            }
            if(!flag) return flag;
            return generalMoveLimit(side, row, col, room);
        }

    }
    //嗔猪
    private static class AngryBoar extends Chess {
        public AngryBoar(int side, int row, int col) {
            super(side, row, col);
        }

        @Override
        public String getName() { return "嗔豬";}

        private final int disCnt=6;
        private final int[] disIndexRow={-1,0,1,-1,0,1};
        private final int[] disIndexCol={-1,-1,-1,1,1,1};

        @Override
        public boolean isPosCanMove(int row, int col, SevenBeatsRoom room) {
            boolean flag=false;
            int disRow=row-this.row,disCol=col-this.col;
            for(int i=0;i<this.disCnt;i++){
                if(disRow==this.disIndexRow[i] && disCol==this.disIndexCol[i]){
                    flag=true;
                    break;
                }
            }
            if(!flag) return flag;
            return generalMoveLimit(side, row, col, room);
        }
    }
    //金将
    private static class Gold extends Chess {
        public Gold(int side, int row, int col) {
            super(side, row, col);
        }

        @Override
        public String getName() { return "金將";}

        private final int disCnt=6;
        private final int[] disIndexRow={1,1,1,0,0,-1};
        private final int[] disIndexCol={-1,0,1,-1,1,0};

        @Override
        public boolean isPosCanMove(int row, int col, SevenBeatsRoom room) {
            boolean flag=false;
            int disRow=row-this.row,disCol=col-this.col;
            if(side==2) disRow*=-1; //另一方的方向是反过来的!!!!
            for(int i=0;i<this.disCnt;i++){
                if(disRow==this.disIndexRow[i] && disCol==this.disIndexCol[i]){
                    flag=true;
                    break;
                }
            }
            if(!flag) return flag;
            return generalMoveLimit(side, row, col, room);
        }
    }
    //天马
    private static class Pegasus extends Chess {
        public Pegasus(int side, int row, int col) {
            super(side, row, col);
        }

        @Override
        public String getName() { return "天馬";}

        private final int disCnt=6;
        private final int[] disIndexRow={-2,-2,1,1,2,2};
        private final int[] disIndexCol={-1,1,-2,2,-1,1};

        @Override
        public boolean isPosCanMove(int row, int col, SevenBeatsRoom room) {
            boolean flag=false;
            int disRow=row-this.row,disCol=col-this.col;
            if(side==2) disRow*=-1; //另一方的方向是反过来的!!!!
            for(int i=0;i<this.disCnt;i++){
                if(disRow==this.disIndexRow[i] && disCol==this.disIndexCol[i]){
                    flag=true;
                    break;
                }
            }
            if(!flag) return flag;
            return generalMoveLimit(side, row, col, room);
        }
    }
}
